package com.gitee.wsl.compose.use.redux

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import com.gitee.wsl.compose.use._useState
import com.gitee.wsl.compose.use.coroutines.useAsync

/**
 * Description:
 * @author Junerver
 * date: 2024/1/26-14:21
 * Email: junerver@gmail.com
 * Version: v1.1
 * update: 2024/3/11 10:57
 * 删除了模板代码，Action 使用 sealed 似乎是更好的决定
 * update: 2024/3/19 13:48
 * action类型从 Any 修改为泛型 A
 */
// reducer 函数类型抽象
typealias Reducer<S, A> = (prevState: S, action: A) -> S

typealias Dispatch<A> = (A) -> Unit

// 定义中间件类型
typealias Middleware<S, A> = (dispatch: Dispatch<A>, state: S) -> Dispatch<A>

/*@Composable
fun <S, A> useReducer(
    reducer: Reducer<S, A>,
    initialState: S,
    middlewares: Array<Middleware<S, A>> = emptyArray(),
): Tuple2<S, Dispatch<A>> {
    val (state, setState) = com.gitee.wsl.compose.state.S.state(initialState)
    val dispatch = { action: A -> setState(reducer(state, action)) }

    val enhancedDispatch: Dispatch<A> = { action ->
        var nextDispatch: Dispatch<A> = dispatch
        for (middleware in middlewares) {
            nextDispatch = middleware(nextDispatch, state)
        }
        nextDispatch(action)
    }

    return Tuple2(state, enhancedDispatch)
}*/


/*
  Description:
  Author: Junerver
  Date: 2024/1/26-14:21
  Email: junerver@gmail.com
  Version: v1.2

  update: 2024/3/11 10:57
  删除了模板代码，Action 使用 sealed 似乎是更好的决定

  update: 2024/3/19 13:48
  action类型从 Any 修改为泛型 A
*/

@Composable
fun <S, A> useReducer(reducer: Reducer<S, A>, initialState: S, middlewares: Array<Middleware<S, A>> = emptyArray()): ReducerHolder<S, A> {
    val asyncRun = useAsync()
    val state = _useState(initialState)
    val dispatch = { action: A -> state.value = reducer(state.value, action) }
    val enhancedDispatch: Dispatch<A> = if (middlewares.isNotEmpty()) {
        { action ->
            var nextDispatch: Dispatch<A> = dispatch
            for (middleware in middlewares) {
                nextDispatch = middleware(nextDispatch, state.value)
            }
            nextDispatch(action)
        }
    } else {
        dispatch
    }
    val enhancedDispatchAsync: DispatchAsync<A> = { block ->
        asyncRun {
            enhancedDispatch(block(enhancedDispatch))
        }
    }
    return remember { ReducerHolder(state, enhancedDispatch, enhancedDispatchAsync) }
}

@Stable
data class ReducerHolder<S, A>(
    val state: State<S>,
    val dispatch: Dispatch<A>,
    val dispatchAsync: DispatchAsync<A>,
)



/**
 * Combines multiple reducers into single reducer chain
 */
fun <S, A> combineReducers(vararg reducers: Reducer<S, A>): Reducer<S, A> = { state, action ->
    reducers.fold(state) { s, reducer -> reducer(s, action) }
}

/**
 * Combines two reducers with the + operator.
 */
operator fun <S, A> Reducer<S, A>.plus(other: Reducer<S, A>): Reducer<S, A> = { s, a ->
    other(this(s, a), a)
}
